/*
 * Copyright 2011 Philippe Blanc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package me.l1k3.fx.client.impl;

import com.google.gwt.dom.client.Element;

import me.l1k3.core.client.queue.Queue;
import me.l1k3.fx.client.channel.inter.Channel;
import me.l1k3.fx.client.channel.inter.ChannelContext;
import me.l1k3.fx.client.engine.FXEngineFactory;
import me.l1k3.fx.client.engine.easing.Easing;
import me.l1k3.fx.client.engine.impl.ChannelContextImpl;
import me.l1k3.fx.client.engine.inter.FXEngine;
import me.l1k3.fx.client.engine.inter.FXEngineConnector;
import me.l1k3.fx.client.inter.FX;
import me.l1k3.fx.client.inter.FXEx;

public abstract class FXAbstract extends FXBase implements FXEx {
	protected FXEngine engine;
	protected ChannelContext context;

	public FXAbstract() {
        engine = initEngine();
	}
	
    @Override
	public FX init(Element element) {
	    context = new ChannelContextImpl();
	    context.setElement(element);
	    
	    return this;
	}
    
    @Override
    public String getType() {
        return engine.toString();
    }
    
    protected FXEngine initEngine() {
        return FXEngineFactory.getEngine(getConnector());
    }
	
    protected FXEngine getEngine() {
		return engine;
	}

	//Some version of java seem to have difficulty with abstract class interface implementation and @Override
    public final FX setEasing(String easing) {
        try {
            engine.setEasing(easing);
        }
        catch(Exception EasingNotSupportedException) {
            setEasing(0.25, 0.1, 0.25, 1.0); //default to ease
        }
        
        return this;
	}

    //Some version of java seem to have difficulty with abstract class interface implementation and @Override
    public final FX setEasing(Easing easing) {
		try {
			engine.setEasing(easing);
		}
		catch(Exception EasingNotSupportedException) {
		    setEasing(0.25, 0.1, 0.25, 1.0); //default to ease
		}
		
		return this;
	}

    //Some version of java seem to have difficulty with abstract class interface implementation and @Override
    public final FX setEasing(double x1, double y1, double x2, double y2) {
        engine.setEasing(x1, y1, x2, y2);
        
        return this;
    }

	@Override
    public abstract FX toggle();

	@Override
    public FX cancel() {
		engine.cancel();
		
		return this;
	}

	@Override
    public Queue animate() {
	    engine.run(1000);
	    return this;
	}

	@Override
    public Queue animate(int duration) {
	    engine.run(duration);
	    return this;
	}

	@Override
    public Queue animate(int duration, int delay, boolean toggle) {
		if(toggle) toggle();
		engine.run(duration, delay);
		return this;
	}
	
	protected void validateChannel(Channel channel) {
	    if(!engine.validateChannel(channel)) {
    	    engine = FXEngineFactory.getHybrid(engine); //and voila no more complain!
    	    engine.validateChannel(channel);
	    }
	}
	
	//- - -
	
	protected abstract void onUpdate(double progress);

    public ChannelContext getContext() {
        return context;
    }
	
	//- - -
    
    protected FXEngineConnector getConnector() {
        return new Connector();
    }
	
	private final class Connector implements FXEngineConnector {
		@Override
		public final void onStart() {
			FXAbstract.this.onStart();
		}

        @Override
        public final void onUpdate(double progress) {
            FXAbstract.this.onUpdate(progress);
        }		
		
		@Override
		public final void onComplete() {    
			FXAbstract.this.onComplete();
		}

		@Override
		public final ChannelContext getContext() {
			return FXAbstract.this.getContext();
		}
	}
	
	@Override
	public String toString() {
	    return "("+super.toString()+") Engine:"+engine.toString();
	}
}
